//
// Created by Suzhen on 2017/5/7.
//

#ifndef ORIONV2_BASICEVENTGENERATOR_H
#define ORIONV2_BASICEVENTGENERATOR_H

#include "Orion.h"
#include "FutureAdapt.hpp"
#include "Utils.h"

ORION_V2_NAMESPACE_BEGIN

    //todo Event Generator 插件化
/**        class BasicEventGenerator;

        struct EventGeneratorPlugin {

            virtual void onInstall(BasicEventGenerator &gen) = 0;

            virtual void onUninstall(BasicEventGenerator &gen) = 0;

            virtual const std::string &getPluginNameTag() const = 0;

        public:
            EventGeneratorPlugin(const EventGeneratorPlugin &) = delete;

            EventGeneratorPlugin &operator=(const EventGeneratorPlugin &) = delete;

            EventGeneratorPlugin(EventGeneratorPlugin &&) = delete;

            EventGeneratorPlugin &operator=(EventGeneratorPlugin &&) = delete;

        };

        struct NamedEventGeneratorPlugin : public EventGeneratorPlugin {
            explicit NamedEventGeneratorPlugin(const std::string &nm)
                    : pluginName_(nm) {
            }

            const std::string &getPluginNameTag() const override {
                return pluginName_;
            }

        private:
            std::string pluginName_;
        };

        struct AsyncEventPlugin : public NamedEventGeneratorPlugin {

            typedef std::function<void()> CallBackType;

            AsyncEventPlugin(const std::string &nm,
                             CallBackType &&callback
            ) : NamedEventGeneratorPlugin(nm), cb_(callback) {
            }

            void onInstall(BasicEventGenerator &gen) override {
                uv_async_init(gen.getGeneratorLoopCtx(), &asyncCtx_, &AsyncEventPlugin::AsyncCb);
            }

            void onUninstall(BasicEventGenerator &gen) override {
                uv_close((uv_handle_t *) &asyncCtx_, &AsyncEventPlugin::AsyncCloseCb);
            }

        private:
            static void AsyncCb(AsyncContext *async) {

            }

            static void AsyncCloseCb(HandleContext *async) {
                
            }

        private:
            AsyncContext asyncCtx_;
            CallBackType cb_;
        };**/

        class BasicEventGenerator : public EnhanceSupport::MRCSupport {
            friend class EventGeneratorPlugin;

        public:

            typedef enum {
                INIT,
                RUNNING,
                CLOSING,
                CLOSED
            } BasicEventGeneratorState;

            typedef std::recursive_mutex GeneratorLockType;
            typedef std::lock_guard<GeneratorLockType> GeneratorLockGuardType;
            typedef std::function<void(BasicEventGenerator &)> TaskType;

        protected:
            virtual ~BasicEventGenerator();

            BasicEventGenerator();

        public:
            static BasicEventGenerator *CreateGenerator();

            static void CloseGenerator(BasicEventGenerator *g);

            static void GeneratorAsyncCb(AsyncContext *async);

            static void GeneratorAsyncClosedCb(uv_handle_t *h);

        public:
            void submitTask(TaskType &&task);

            BasicEventGenerator::BasicEventGeneratorState getState();

            void start(std::function<void()> &&initFn = nullptr);

            Future<bool> startAsync(std::function<void()> &&initFn = nullptr);

            Future<bool> startFuture();

            Future<bool> stopFuture();

            Future<bool> stopAsync();

            CoreLoopContext *getGeneratorLoopCtx();

        public:

            BasicEventGenerator(const BasicEventGenerator &) = delete;

            BasicEventGenerator &operator=(const BasicEventGenerator &) = delete;

            BasicEventGenerator(BasicEventGenerator &&o) = delete;

            BasicEventGenerator &operator=(BasicEventGenerator &&o) = delete;

        protected:
            ThreadId threadId_;
            CoreLoopContext *loopCtx_;
            AsyncContext *asyncCtx_;
            GeneratorLockType internalLock_;
            std::list<TaskType> taskQueue_;
            //
            Promise<bool> closePromise_;
            Promise<bool> startPromise_;
            BasicEventGeneratorState state_;

        };

ORION_V2_NAMESPACE_END


#endif //ORIONV2_BASICEVENTGENERATOR_H
